/*
 * Copyright the original author or authors.
 * 
 * Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.mozilla.org/MPL/MPL-1.1.html
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.kairos.utils.monitor
{
	import com.bourre.structures.Range;	

	/**
	 * An <code>AverageField</code> stores values and produce the
	 * average of thoses values for the <code>Monitor</code>.
	 * 
	 * <p>Subclass it to create your own average monitor field.
	 * See <code>AverageStepField</code> code to see a concret
	 * implementation af an average field.</p>
	 * 
	 * <p>The average can be limited to the N last registered values.
	 * To do that, simply defines the <code>limit</code> parameter of
	 * the <code>AverageField</code> constructor.</p>
	 * 
	 * @author 	Cédric Néhémie
	 * @see		AbstractMonitorField
	 * @see		MonitorField
	 */
	public class AbstractAverageField extends AbstractMonitorField implements MonitorField
	{
		/**
		 * <code>Number</code> of value in the average.
		 */
		protected var _nCount : Number;
		
		/**
		 * <code>Number</code> sum of all values to compute the average.
		 */
		protected var _nSum : Number;
		
		/**
		 * <code>Array</code> of values when average is limited in time.
		 * 
		 * <p>That array isn't used when <code>_nLimit</code> is set
		 * to <code>-1</code>.
		 */
		protected var _aValues : Array;
		
		/**
		 * Max <code>Number</code> of values for computing the average.
		 * 
		 * <p>A value of <code>-1</code> 
		 */
		protected var _nLimit : int;
		
		/**
		 * Call the super constructor to defines common properties of the field.
		 * 
		 * <p>Defines the <code>limit</code> parameter on -1 if you don't want
		 * to have any limit for the number of values in the average.</p> 
		 * 
		 * @param name	<code>String</code> name of the field.
		 * @param val	<code>Number</code> start value of the field.
		 * @param unit	<code>String</code> of the unit for the field.
		 * @param dr	<code>Range</code> of displaed values.
		 * @param limit	<code>Number</code> of values in the average. A value
		 * 				of <code>-1</code> will does that the average will
		 * 				contains all registered values.
		 * @param col	<code>Number</code> color of the field.
		 * @see	AbstractMonitorField#AbstractMonitorField
		 */
		public function AbstractAverageField( name : String = "Untitled", val : Number = 0, unit : String = "ms" , dr : Range = null, limit : int = -1, col:Number = NaN )
		{
			super( name, val, unit, dr, col );
			_nSum = 0;
			_nCount = 0;
			_nLimit = ( limit >= 1 || limit == -1 ) ? limit : -1;
			
			if( _nLimit != -1 )
			{
				_aValues = new Array();
			}
		}
		
		/**
		 * Registers the value and updates the average value.
		 * 
		 * @param n <code>Number</code> current value for the field.
		 */
		protected function _registerValue ( n : Number ) : void
		{
			_nLastValue = _nValue;
			
			if( _nLimit != -1 )
			{
				if( _aValues.length + 1  > _nLimit )
				{
					_nSum -= _aValues.shift() as Number;
					_nCount--;
				}
				_aValues.push( n );
			}
			
			_nSum += n;
			
			_nValue = Math.round( _nSum / ++_nCount );
		}
	}
}